﻿using System;
using System.Runtime.InteropServices;

namespace MatlabBridge.NativeMethods
{
    internal struct mwSize
    {
        public mwSize(int value)
        {
            this.value = value;
        }
        public int value;
    }
    internal struct mwIndex
    {
        public mwIndex(int value)
        {
            this.value = value;
        }
        public int value;
    }

    internal enum mxClassID
    {
        mxUNKNOWN_CLASS = 0,
        mxCELL_CLASS,
        mxSTRUCT_CLASS,
        mxLOGICAL_CLASS,
        mxCHAR_CLASS,
        mxVOID_CLASS,
        mxDOUBLE_CLASS,
        mxSINGLE_CLASS,
        mxINT8_CLASS,
        mxUINT8_CLASS,
        mxINT16_CLASS,
        mxUINT16_CLASS,
        mxINT32_CLASS,
        mxUINT32_CLASS,
        mxINT64_CLASS,
        mxUINT64_CLASS,
        mxFUNCTION_CLASS,
        mxOPAQUE_CLASS,
        mxOBJECT_CLASS
    }
    internal enum mxComplexity
    {
        mxREAL = 0,
        mxCOMPLEX
    }

    internal static class libmx
    {
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern string mxArrayToString(IntPtr array_ptr);

        [DllImport("libmx.dll")]
        public static extern mwIndex mxCalcSingleSubscript(IntPtr pm, mwSize nsubs, mwIndex[] subs);

        [DllImport("libmx.dll")]
        public static extern void mxDestroyArray(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxDuplicateArray(IntPtr @in);

        [DllImport("libmx.dll")]
        public static unsafe extern void* mxCalloc(mwSize n, mwSize size);
        [DllImport("libmx.dll")]
        public static unsafe extern void* mxMalloc(mwSize n);
        [DllImport("libmx.dll")]
        public static unsafe extern void* mxRealloc(void* ptr, mwSize size);
        [DllImport("libmx.dll")]
        public static unsafe extern void mxFree(void* ptr);

        [DllImport("libmx.dll")]
        public static unsafe extern int mxAddField(IntPtr pm, string fieldname);
        [DllImport("libmx.dll")]
        public static unsafe extern void mxRemoveField(IntPtr pm, int fieldnumber);

        #region mxCreate*
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateCellArray(mwSize ndim, mwSize[] dims);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateNumericArray(mwSize ndim, int[] dims, mxClassID classid, mxComplexity ComplexFlag);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateSparse(mwSize m, mwSize n, mwSize nzmax, mxComplexity ComplexFlag);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateSparseLogicalMatrix(mwSize m, mwSize n, mwSize nzmax);
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern IntPtr mxCreateStructArray(mwSize ndim, int[] dims, int nfields, string[] fieldnames);

        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateDoubleScalar(double value);
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern IntPtr mxCreateString(string str);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateLogicalScalar(bool value);

        // -- unused --
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateCellMatrix(mwSize m, mwSize n);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateCharArray(mwSize ndim, mwSize[] dims);
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern IntPtr mxCreateCharMatrixFromStrings(mwSize m, string[] str);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateDoubleMatrix(mwSize m, mwSize n, mxComplexity ComplexFlag);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateLogicalArray(mwSize ndim, mwSize[] dims);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateLogicalMatrix(mwSize m, mwSize n);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxCreateNumericMatrix(mwSize m, mwSize n, mxClassID classid, mxComplexity ComplexFlag);
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern IntPtr mxCreateStructMatrix(mwSize m, mwSize n, int nfields, string[] fieldnames);
        #endregion

        #region mxGet*
        [DllImport("libmx.dll")]
        public static extern double mxGetInf();
        [DllImport("libmx.dll")]
        public static extern double mxGetNaN();

        [DllImport("libmx.dll")]
        public static extern IntPtr mxGetCell(IntPtr pm, mwIndex index);
        [DllImport("libmx.dll")]
        public static extern char[] mxGetChars(IntPtr array_ptr);
        [DllImport("libmx.dll")]
        public static extern mxClassID mxGetClassID(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern string mxGetClassName(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxGetData(IntPtr pm);
        [DllImport("libmx.dll")]
        public static unsafe extern IntPtr mxGetDimensions(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern mwSize mxGetElementSize(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern double mxGetEps();
        [DllImport("libmx.dll")]
        public static extern IntPtr mxGetField(IntPtr pm, mwIndex index, string fieldname);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxGetFieldByNumber(IntPtr pm, mwIndex index, int fieldnumber);
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern string mxGetFieldNameByNumber(IntPtr pm, int fieldnumber);
        [DllImport("libmx.dll")]
        public static extern int mxGetFieldNumber(IntPtr pm, string fieldname);
        [DllImport("libmx.dll")]
        public static unsafe extern void* mxGetImagData(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern mwIndex[] mxGetIr(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern mwIndex[] mxGetJc(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool[] mxGetLogicals(IntPtr array_ptr);
        [DllImport("libmx.dll")]
        public static extern mwSize mxGetM(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern mwSize mxGetN(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern mwSize mxGetNumberOfDimensions(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern mwSize mxGetNumberOfElements(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern int mxGetNumberOfFields(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern mwSize mxGetNzmax(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxGetPi(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern IntPtr mxGetPr(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern double mxGetScalar(IntPtr pm);
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern int mxGetString(IntPtr pm, IntPtr buffer, mwSize strlen);
        #endregion

        #region mxIs*
        [DllImport("libmx.dll")]
        public static extern bool mxIsFinite(double value);
        [DllImport("libmx.dll")]
        public static extern bool mxIsInf(double value);
        [DllImport("libmx.dll")]
        public static extern bool mxIsNaN(double value);

        [DllImport("libmx.dll")]
        public static extern bool mxIsCell(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsClass(IntPtr pm, string classname);
        [DllImport("libmx.dll")]
        public static extern bool mxIsComplex(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsEmpty(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsFromGlobalWS(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsLogicalScalar(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsLogicalScalarTrue(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsNumeric(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsSparse(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsStruct(IntPtr pm);

        [DllImport("libmx.dll")]
        public static extern bool mxIsChar(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsDouble(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsInt16(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsInt32(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsInt64(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsInt8(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsLogical(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsSingle(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsUint16(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsUint32(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsUint64(IntPtr pm);
        [DllImport("libmx.dll")]
        public static extern bool mxIsUint8(IntPtr pm);
        #endregion

        #region mxSet*
        [DllImport("libmx.dll")]
        public static extern void mxSetCell(IntPtr pm, mwIndex index, IntPtr value);
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern int mxSetClassName(IntPtr array_ptr, string classname);
        [DllImport("libmx.dll")]
        public static unsafe extern void mxSetData(IntPtr pm, void* pr);
        [DllImport("libmx.dll")]
        public static extern int mxSetDimensions(IntPtr pm, mwSize[] dims, mwSize ndim);
        [DllImport("libmx.dll", CharSet = CharSet.Ansi)]
        public static extern void mxSetField(IntPtr pm, mwIndex index, string fieldname, IntPtr value);
        [DllImport("libmx.dll")]
        public static extern void mxSetFieldByNumber(IntPtr pm, mwIndex index, int fieldnumber, IntPtr value);
        [DllImport("libmx.dll")]
        public static unsafe extern void mxSetImagData(IntPtr pm, void* pi);
        [DllImport("libmx.dll")]
        public static extern void mxSetIr(IntPtr pm, mwIndex[] ir);
        [DllImport("libmx.dll")]
        public static extern void mxSetJc(IntPtr pm, mwIndex[] jc);
        [DllImport("libmx.dll")]
        public static extern void mxSetM(IntPtr pm, mwSize m);
        [DllImport("libmx.dll")]
        public static extern void mxSetN(IntPtr pm, mwSize n);
        [DllImport("libmx.dll")]
        public static extern void mxSetNzmax(IntPtr pm, mwSize nzmax);
        [DllImport("libmx.dll")]
        public static extern void mxSetPi(IntPtr pm, double[] pi);
        [DllImport("libmx.dll")]
        public static extern void mxSetPr(IntPtr pm, double[] pr);
        #endregion
    }
}
